home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1997
/
MacHack 1997.toast
/
Hacks
/
Hacks ’97
/
Animated Icons
/
Source
/
IconSuitePatches.cp
< prev
next >
Wrap
Text File
|
1997-07-02
|
38KB
|
1,699 lines
#define DONTDEFINEMACROS 1
#include "AnimatedIcons.h"
#include "IconSuitePatches.h"
#include "Icons.h"
#include <limits.h>
#include <Traps.h>
#include <LArray.h>
#include <LArrayIterator.h>
#include <A4Stuff.h>
#include <QDOffscreen.h>
#include "LogInterface.h"
#ifndef BUILDINGINIT
#include <iostream.h>
#endif
UniversalProcPtr gOriginalIconUtilitiesAddr = 0;
UniversalProcPtr gOriginalIconServicesAddr = 0;
UniversalProcPtr gOriginalInitGrafAddr = 0;
UniversalProcPtr gOriginalDisposeWindowTrapAddr = 0;
UniversalProcPtr gOriginalHideWindowTrapAddr = 0;
UniversalProcPtr gOriginalCopybitsAddr = 0;
UniversalProcPtr gOriginalQDUtilitiesAddr = nil;
#include <stdarg.h>
#include <stdio.h>
LArray* sFinderOffscreenGWorldList = nil;
LogInterfacePtr sLogP = nil;
#if 1
int vdprintf( const char * format, va_list arg)
{
#if BUILDINGINIT
Str255 buf;
buf[0] = vsprintf ( (char*) & buf[1], format, arg );
DebugStr ( buf );
if ( ! sLogP )
sLogP = GetLogInterfacePtr();
InsertIntoRing ( sLogP, (char*) & buf[1], buf[0] );
#else
vprintf ( format, arg );
printf ( "\n" );
#endif
}
int dprintf(const char * format, ...)
{ va_list args;
va_start(args, format );
int result = vdprintf ( format, args );
va_end ( args );
return result;
}
#else
inline int dprintf(const char * format, ...) { return 0; };
#endif
/***********************************|****************************************
*
* Boolean IsOptionKeyDown ( )
*
* Return true if the option key is currently depressed; false otherwise.
*
***********************************|****************************************/
Boolean IsOptionKeyDown ( );
Boolean IsOptionKeyDown ( )
{ KeyMap map;
const unsigned short optionKeyCode = 0x3a;
GetKeys ( map );
long c = ( ((unsigned char*) &map ) [ optionKeyCode >> 3 ] >> ( optionKeyCode & 7 ) );
return c & 0x01;
// return ((*(long *)0x178 & 4L) != 0L);
}
#ifdef BUILDINGINIT
OSType gGlobalsCheck = 'KSDC';
#define CheckGlobals() { if ( gGlobalsCheck != 'KSDC' ) Debugger(); }
// ============================================================================================
void* operator new ( size_t s )
{
return NewPtrSysClear ( s );
}
void operator delete ( void* p )
{
DisposePtr( (Ptr) p );
}
// ============================================================================================
static asm unsigned long GetA0()
{
move.l a0, d0
rts
}
// ============================================================================================
pascal void main ( )
{
// Debugger();
Handle ourCodeH = (Handle) GetA0();
SetZone ( SystemZone() );
EnterCodeResource ();
if ( ourCodeH && *ourCodeH && HandleZone( ourCodeH ) == SystemZone() )
{
DetachResource ( ourCodeH );
InstallAllUniversalPatches ();
}
ExitCodeResource ();
}
#include "console.stubs.c"
#else
#define CheckGlobals() { }
#endif
#if PATCHTRAPS
// ============================================================================================
asm pascal OSErr CallGetIconSuite ( Handle *theIconSuite, SInt16 theResID, IconSelectorValue selector )
{
move.w #0x0501, d0
move.l gOriginalIconUtilitiesAddr, -(sp)
rts
}
asm pascal OSErr CallPlotIconSuite ( const Rect *theRect, IconAlignmentType align, IconTransformType transform, Handle theIconSuite )
{
move.w #0x0603, d0
move.l gOriginalIconUtilitiesAddr, -(sp)
rts
}
asm pascal OSErr CallDisposeIconSuite ( Handle theIconSuite, Boolean disposeData )
{
move.w #0x302, d0
move.l gOriginalIconUtilitiesAddr, -(sp)
rts
}
// ============================================================================================
asm pascal OSErr CallGetIconRefFromFile ( const FSSpec *theFile, IconRef *iconRef, SInt16 *theLabel )
{
move.w #0x2, d0
move.l gOriginalIconServicesAddr, -(sp)
rts
}
asm pascal OSErr CallGetIconRefFromFileInfo ( const FSSpec *theFile, IconRef *iconRef, OSType creator, OSType fileType, Boolean hasCustomIcon )
{
move.w #0x3, d0
move.l gOriginalIconServicesAddr, -(sp)
rts
}
asm pascal OSErr CallGetIconRefFromFolderInfo ( SInt16 vRefNum, SInt32 folderID, IconRef *iconRef, OSType fileType, Boolean hasCustomIcon )
{
move.w #0x4, d0
move.l gOriginalIconServicesAddr, -(sp)
rts
}
asm pascal OSErr CallPlotIconRef ( const Rect *theRect, IconAlignmentType align, IconTransformType transform, IconServicesUsageFlags iconServicesUsageFlags, IconRef theIconRef )
{
move.w #0xe, d0
move.l gOriginalIconServicesAddr, -(sp)
rts
}
asm pascal OSErr CallDisposeIconRef ( IconRef theIconRef )
{
move.w #0xd, d0
move.l gOriginalIconServicesAddr, -(sp)
rts
}
asm pascal void CallCopyBits ( BitMap* srcBits, BitMap* destBits,
const Rect* srcRect, const Rect* destRect,
short mode,
RgnHandle maskRgn )
{
move.l gOriginalCopybitsAddr, a0
jmp (a0)
}
asm pascal OSErr CallNewGWorldRoutine ( GWorldPtr *offscreenGWorld, short PixelDepth,
const Rect *boundsRect, CTabHandle cTable,
GDHandle aGDevice, GWorldFlags flags )
{
move.l #0x00160000, d0
move.l gOriginalQDUtilitiesAddr, -(sp)
rts
}
asm pascal OSErr CallUpdateGWorldRoutine ( GWorldPtr *offscreenGWorld, short PixelDepth,
const Rect *boundsRect, CTabHandle cTable,
GDHandle aGDevice, GWorldFlags flags )
{
move.l #0x00160003, d0
move.l gOriginalQDUtilitiesAddr, -(sp)
rts
}
asm pascal void CallDisposeGWorld ( GWorldPtr offscreenGWorld )
{
move.l #0x00040004, d0
move.l gOriginalQDUtilitiesAddr, -(sp)
rts
}
// ============================================================================================
#endif
static asm unsigned long GetA4()
{
move.l a4, d0
rts
}
static asm unsigned long GetA5()
{
move.l a5, d0
rts
}
static UniversalProcPtr PatchTrap ( unsigned short trapNumber, UniversalProcPtr newValue, Boolean keithsSpecialTrapHeader = true )
{ UniversalProcPtr result = GetToolTrapAddress ( trapNumber );
if ( keithsSpecialTrapHeader )
{
char* patchRoutine = (char*) newValue;
* ( UniversalProcPtr *) ( ( patchRoutine ) + 2 ) = result;
#ifdef BUILDINGINIT
* ( unsigned long *) ( ( patchRoutine ) + 6 ) = GetA4();
#else
* ( unsigned long *) ( ( patchRoutine ) + 6 ) = GetA5();
#endif
}
SetToolTrapAddress ( (UniversalProcPtr) newValue, trapNumber );
return result;
}
pascal void InstallGNEFilter ( )
{
#ifdef BUILDINGINIT
static Boolean installed = false;
if ( ! installed )
{ GNEFilterUPP originalGNEFilterProc = LMGetGNEFilter();
char* patchRoutine = (char*) jGNEFilter;
* ( UniversalProcPtr *) ( ( patchRoutine ) + 2 ) = (UniversalProcPtr) originalGNEFilterProc;
#ifdef BUILDINGINIT
* ( unsigned long *) ( ( patchRoutine ) + 6 ) = GetA4();
#else
* ( unsigned long *) ( ( patchRoutine ) + 6 ) = GetA5();
#endif
LMSetGNEFilter ( (GNEFilterUPP) jGNEFilter );
installed = true;
}
#endif
}
pascal void InstallAllUniversalPatches ( )
{
InstallIconUtilitiesPatches ();
InstallDisposeWindowPatch ();
#ifdef BUILDINGINIT
InstallGNEFilter();
#endif
}
pascal void InstallIconUtilitiesPatches ( )
{
#if PATCHTRAPS
static Boolean installed = false;
if ( ! installed )
{
installed = true;
gOriginalIconUtilitiesAddr = PatchTrap ( _IconDispatch, (UniversalProcPtr) & IconUtilitiesTrapPatch );
gOriginalInitGrafAddr = PatchTrap ( _InitGraf, (UniversalProcPtr) & InitGrafPatch );
}
#endif
if ( ! gIconsToAnimate )
gIconsToAnimate = new LArray ( sizeof( void*) );
if ( ! gIconsOnScreen )
gIconsOnScreen = new LArray ( sizeof( void*) );
if ( ! sFinderOffscreenGWorldList )
sFinderOffscreenGWorldList = new LArray ( sizeof( void*) );
}
pascal void InstallIconServicesPatches ( )
{
#if PATCHTRAPS
static Boolean installed = false;
const unsigned short _IconServicesTrap = 0xaa75;
if ( ! installed )
{
installed = true;
gOriginalIconServicesAddr = PatchTrap ( _IconServicesTrap, (UniversalProcPtr) & IconServicesTrapPatch );
}
#endif
}
pascal void InstallDisposeWindowPatch ( )
{
#if PATCHTRAPS
static Boolean installed = false;
if ( ! installed )
{
installed = true;
gOriginalDisposeWindowTrapAddr = PatchTrap ( _DisposeWindow, (UniversalProcPtr) & DisposeWindowPatch );
gOriginalHideWindowTrapAddr = PatchTrap ( _DisposeWindow, (UniversalProcPtr) & HideWindowPatch );
}
#endif
}
pascal void InstallCopyBitsPatch ( )
{
#if PATCHTRAPS
static Boolean installed = false;
if ( ! installed )
{
installed = true;
gOriginalCopybitsAddr = PatchTrap ( _CopyBits, (UniversalProcPtr) & CopyBitsPatch, true );
gOriginalQDUtilitiesAddr = PatchTrap ( _QDExtensions, (UniversalProcPtr) & QDExtensionsPatch, true );
}
#endif
}
class StUseSystemHeap
{
public: StUseSystemHeap ( ) { mSavedZone = GetZone(); SetZone ( SystemZone() ); };
~StUseSystemHeap ( ) { if ( mSavedZone ) SetZone( mSavedZone ); };
void RestoreHeap ( ) { SetZone ( mSavedZone ); mSavedZone = nil; };
protected:
THz mSavedZone;
};
pascal OSErr NewIconSuiteFromFilePatch (const FSSpec *spec, IconSelectorValue whichIcons, Handle *iconSuite, IconServicesUsageFlags iconServicesUsageFlags)
{
short savedCurResFile = CurResFile();
Handle originalTopMapH = LMGetTopMapHndl ();
short resFileRefNum = FSpOpenResFile ( spec, fsRdPerm );
OSErr result = ResError();
if ( result == noErr )
{
Handle newTopMapH = LMGetTopMapHndl();
Boolean closeResFileAfterWeAreDone = ( originalTopMapH != newTopMapH );
result = GetIconSuite ( iconSuite, kCustomIconResource, whichIcons );
if ( resFileRefNum && closeResFileAfterWeAreDone )
CloseResFile ( resFileRefNum );
}
UseResFile ( savedCurResFile );
return result;
}
// ============================================================================================
static pascal OSErr GetIconSuiteAndRefCommon ( const void* theIconRef, FSSpec* spec, short resFileRefNum, short theResID )
{ StUseSystemHeap saveZone;
short savedResFile = CurResFile();
UseResFile ( resFileRefNum );
Handle h = Get1Resource ( 'AICN', theResID );
if ( h && *h )
{
AnimatedIcon* a = new FrameAnimatedIcon ( theIconRef, (FrameAnimatedIcon::FrameAnimatedIconResourceHandle) h );
ReleaseResource ( h );
dprintf ( "Frame: %lx -> %lx", (void*) theIconRef, a );
}
else if ( ( h = Get1Resource ( 'MICN', theResID ) ) && *h && QuicktimeMovieAnimatedIcon::IsQuicktimeAvailable() )
{
QuicktimeMovieAnimatedIcon* movieAnimation = new QuicktimeMovieAnimatedIcon ( theIconRef, (QuicktimeMovieAnimatedIcon::QuicktimeMovieAnimatedIconResourceHandle) h, spec, 0 );
ReleaseResource ( h );
dprintf ( "Quicktime: %lx -> %lx", (void*) theIconRef, movieAnimation );
}
else if ( ( h = Get1Resource ( 'PICN', theResID ) ) && *h )
{
PictureAnimatedIcon* pictureAnimation = new PictureAnimatedIcon ( theIconRef, (PictureAnimatedIcon::PictureAnimatedIconResourceHandle) h );
ReleaseResource ( h );
dprintf ( "Picture: %lx -> %lx", (void*) theIconRef, pictureAnimation );
}
else if ( ( h = Get1Resource ( 'ßICN', theResID ) ) && *h )
{
SoundAnimatedIcon* pictureAnimation = new SoundAnimatedIcon ( theIconRef, (SoundAnimatedIcon::SoundAnimatedIconResourceHandle) h );
ReleaseResource ( h );
}
else if ( ( h = Get1Resource ( 'VICN', theResID ) ) && *h )
{
VoiceAnimatedIcon* pictureAnimation = new VoiceAnimatedIcon ( theIconRef, (VoiceAnimatedIcon::VoiceAnimatedIconResourceHandle) h, spec );
ReleaseResource ( h );
}
UseResFile ( savedResFile );
return noErr;
}
// ============================================================================================
pascal OSErr GetIconSuitePatch (Handle *theIconSuite, SInt16 theResID, IconSelectorValue selector)
{
CheckGlobals();
OSErr result = CallGetIconSuite ( theIconSuite, theResID, selector );
if ( result == noErr )
result = GetIconSuiteAndRefCommon ( *theIconSuite, nil, CurResFile(), theResID );
return result;
}
// ============================================================================================
static pascal OSErr GetIconRefCommon ( const FSSpec* spec, IconRef *theIconRef, short theResID )
{ StUseSystemHeap saveZone;
short savedCurResFile = CurResFile();
Handle originalTopMapH = LMGetTopMapHndl ();
short resFileRefNum = FSpOpenResFile ( spec, fsRdPerm );
OSErr result = ResError();
if ( result == noErr )
{
Handle newTopMapH = LMGetTopMapHndl();
Boolean closeResFileAfterWeAreDone = ( originalTopMapH != newTopMapH );
result = GetIconSuiteAndRefCommon ( *theIconRef, spec, CurResFile(), theResID );
if ( resFileRefNum && closeResFileAfterWeAreDone )
CloseResFile ( resFileRefNum );
}
UseResFile ( savedCurResFile );
return noErr;
}
// ============================================================================================
pascal OSErr GetIconRefFromFilePatch ( const FSSpec* spec, IconRef *theIconRef, SInt16* label )
{
CheckGlobals();
OSErr result = CallGetIconRefFromFile ( spec, theIconRef, label );
if ( result == noErr )
result = GetIconRefCommon ( spec, theIconRef, kCustomIconResource );
return result;
}
pascal OSErr GetIconRefFromFileInfoPatch ( const FSSpec *spec, IconRef *iconRef, OSType creatorCode, OSType fileType, Boolean hasCustomIcon )
{
CheckGlobals();
OSErr result = CallGetIconRefFromFileInfo ( spec, iconRef, creatorCode, fileType, hasCustomIcon );
if ( result == noErr && hasCustomIcon )
result = GetIconRefCommon ( spec, iconRef, kCustomIconResource );
return result;
}
extern pascal OSErr GetIconRefFromFolderInfoPatch (SInt16 vRefNum, SInt32 folderID, IconRef *iconRef, OSType fileType, Boolean hasCustomIcon)
{
CheckGlobals();
OSErr result = CallGetIconRefFromFolderInfo ( vRefNum, folderID, iconRef, fileType, hasCustomIcon );
if ( result == noErr && hasCustomIcon )
{ FSSpec spec;
result = FSMakeFSSpec ( vRefNum, folderID, "\pIcon\r", & spec );
if ( result == noErr )
result = GetIconRefCommon ( & spec, iconRef, kCustomIconResource );
}
return result;
}
// ============================================================================================
pascal OSErr PlotIconSuitePatch (const Rect *theRect, IconAlignmentType align, IconTransformType transform, Handle theIconSuite)
{ StUseSystemHeap saveZone;
OSErr result = noErr;
CheckGlobals();
GrafPtr currentPort;
GetPort ( & currentPort );
AnimatedIconOnScreen* a = AnimatedIconOnScreen::GetAnimatedIconOnScreen ( currentPort, *theRect, theIconSuite );
AnimatedIcon* animatedIcon = nil;
if ( ! a )
{
animatedIcon = AnimatedIcon::GetAnimatedIconForIconSuite ( theIconSuite );
if ( animatedIcon )
{
a = animatedIcon->GetNewAnimatedIconOnScreen( currentPort, theRect, align, transform );
}
gNextTickToCheckAnimations = 0;
}
if ( a && transform == ttNone )
result = a->Draw( theRect, align, transform );
else
result = errForceCallToOriginalPlotIcon;
if ( result == errForceCallToOriginalPlotIcon )
{
saveZone.RestoreHeap ();
result = ::CallPlotIconSuite ( theRect, align, transform, theIconSuite );
}
SetPort ( currentPort );
return result;
}
pascal OSErr PlotIconRefPatch (const Rect *theRect, IconAlignmentType align, IconTransformType transform, IconServicesUsageFlags iconServicesUsageFlags, IconRef iconRef )
{ OSErr result = noErr;
CheckGlobals();
StUseSystemHeap saveZone;
GrafPtr currentPort;
GetPort ( & currentPort );
AnimatedIconOnScreen* a = AnimatedIconOnScreen::GetAnimatedIconOnScreen ( currentPort, *theRect, iconRef );
AnimatedIcon* animatedIcon = nil;
if ( ! a )
{
animatedIcon = AnimatedIcon::GetAnimatedIconForIconSuite ( iconRef );
if ( animatedIcon )
{
a = animatedIcon->GetNewAnimatedIconOnScreen( currentPort, theRect, align, transform );
dprintf ( "Making new animIcon %lx for ref=%lx", a, iconRef );
}
gNextTickToCheckAnimations = 0;
}
if ( a )
dprintf ( "PlotIconRef: subst %lx trans=%d port %lx", a, transform, a->GetPort() );
if ( a && ( ( transform == ttNone ) || ( transform == ttSelected ) ) )
{
result = a->Draw( theRect, align, transform );
}
else
result = errForceCallToOriginalPlotIcon;
if ( result == errForceCallToOriginalPlotIcon )
{
saveZone.RestoreHeap();
result = ::CallPlotIconRef ( theRect, align, transform, iconServicesUsageFlags, iconRef );
}
return result;
}
// ============================================================================================
pascal OSErr DisposeIconSuitePatch (Handle theIconSuite, Boolean disposeData)
{
CheckGlobals();
AnimatedIcon* a = AnimatedIcon::GetAnimatedIconForIconSuite ( theIconSuite );
if ( a )
{ StUseSystemHeap saveZone;
AnimatedIconOnScreen* animatedIcon = nil;
for ( LArrayIterator iter ( *gIconsOnScreen ); iter.Next( & animatedIcon ); )
if ( animatedIcon && animatedIcon->GetAnimatedIcon() == a )
delete animatedIcon;
delete a;
}
OSErr result = CallDisposeIconSuite ( theIconSuite, disposeData );
return result;
}
pascal OSErr DisposeIconRefPatch ( IconRef iconRef )
{ StUseSystemHeap saveZone;
CheckGlobals();
dprintf ( "DisposeIconRefCommon, icon=%lx", iconRef );
if ( iconRef )
{ StUseSystemHeap saveZone;
AnimatedIcon* a = AnimatedIcon::GetAnimatedIconForIconSuite ( iconRef );
if ( a )
{
AnimatedIconOnScreen* animatedIcon = nil;
for ( LArrayIterator iter ( *gIconsOnScreen ); iter.Next( & animatedIcon ); )
if ( animatedIcon && animatedIcon->GetAnimatedIcon() == a )
delete animatedIcon;
delete a;
}
}
OSErr result = CallDisposeIconRef ( iconRef );
return result;
}
// ============================================================================================
static WindowPeek FindWindowInWindowList ( GrafPtr windowToFindP )
{ WindowPeek result = nil;
for ( WindowPeek windowP = (WindowPeek) FrontWindow(); windowP; windowP = windowP->nextWindow )
{
if ( (WindowPtr) windowP == (WindowPtr) windowToFindP )
{
result = windowP;
break;
}
}
return result;
}
// ============================================================================================
static GrafPtr FindWindowForBitMap ( BitMap* bitMap )
{ GrafPtr result = nil;
for ( WindowPeek windowP = (WindowPeek) FrontWindow(); windowP; windowP = windowP->nextWindow )
{
if ( windowP->port.portBits.rowBytes & 0x8000 )
{
if ( ( & windowP->port.portBits == bitMap ) )
{
result = (GrafPtr) windowP;
break;
}
}
else if ( windowP->port.portBits.baseAddr == bitMap->baseAddr )
{
result = (GrafPtr) windowP;
break;
}
}
return result;
}
// ============================================================================================
static unsigned long InvalidateCurrentIcons ( Boolean drawIconsAsWell = true )
{ AnimatedIconOnScreen* animatedIcon = nil;
GrafPtr savedPort;
static unsigned long nextInvalidateTick = 0;
unsigned long result = ULONG_MAX;
GetPort ( & savedPort );
unsigned long now = TickCount();
Boolean invalidateIconsAsWell = ( nextInvalidateTick < TickCount() );
for ( LArrayIterator iter ( *gIconsOnScreen ); iter.Next( & animatedIcon ); )
{
dprintf ( "Inval: %lx port:%lx ", animatedIcon, (void*) animatedIcon->GetPort() );
if ( animatedIcon && animatedIcon->GetNextAnimationTick() <= now)
{
if ( ! FindWindowInWindowList ( animatedIcon->GetPort() ) )
continue;
SetPort ( animatedIcon->GetPort() );
animatedIcon->Advance();
if ( ! drawIconsAsWell || invalidateIconsAsWell )
{
InvalRect ( & animatedIcon->GetRect() );
animatedIcon->IncrementCountOfTimesThisHasBeenInvalidated();
}
animatedIcon->Idle();
if ( animatedIcon->GetNextAnimationTick() < result )
result = animatedIcon->GetNextAnimationTick();
if ( animatedIcon->GetCountOfTimesThisHasBeenInvalidated() > 6 )
delete animatedIcon;
}
}
if ( invalidateIconsAsWell )
nextInvalidateTick = TickCount() + 30;
SetPort ( savedPort );
return result;
}
static pascal void DisposeWindowRoutine ( WindowPtr windowP )
{ AnimatedIconOnScreen* animatedIcon = nil;
CheckGlobals();
for ( LArrayIterator iter ( *gIconsOnScreen ); iter.Next( & animatedIcon ); )
{
if ( animatedIcon && animatedIcon->GetPort() == windowP )
delete animatedIcon;
}
}
static pascal void CopyBitsRoutine ( BitMap* srcBits, BitMap* destBits,
const Rect* srcRect, const Rect* destRect,
short mode, RgnHandle maskRgn )
{ AnimatedIconOnScreen* animatedIcon = nil;
RgnHandle maskRgnMinusIconsWeAreMirroring = nil;
Debugger ();
if ( srcBits != destBits )
{ WindowPtr destWindow = nil;
GWorldPtr offscreenGWorld = nil;
for ( LArrayIterator iter ( *sFinderOffscreenGWorldList ); iter.Next( & offscreenGWorld ); )
{
dprintf ( "CopyBits1: offscreenGWorld=%x bits=%x srcBits=%x",
offscreenGWorld, & offscreenGWorld->portPixMap, srcBits );
if ( offscreenGWorld && offscreenGWorld->portPixMap && *offscreenGWorld->portPixMap &&
(void*) & ** offscreenGWorld->portPixMap == (void*) srcBits )
{
if ( destWindow == nil )
{
destWindow = FindWindowForBitMap ( destBits );
if ( ! destWindow )
break;
}
dprintf ( "CopyBits2: Move icon=%x from port=%x to port %x",
animatedIcon, offscreenGWorld, destWindow );
if ( destWindow )
animatedIcon->SetPort ( destWindow );
}
}
for ( LArrayIterator iter ( *gIconsOnScreen ); iter.Next( & animatedIcon ); )
{
// Otherwise, if the destination for this copybits is the same port as this icon,
// then subtract the region we're mirroring this icon from the mask for the
// copybits. This keeps the Finder from overwriting our icons on the screen
if ( animatedIcon && animatedIcon->GetPort()->portBits.baseAddr == destBits->baseAddr )
{
dprintf ( "CopyBits: Subtracting this icon from port=%x rect=%d %d %d %d",
animatedIcon, animatedIcon->GetRect().top, animatedIcon->GetRect().left, animatedIcon->GetRect().bottom, animatedIcon->GetRect().right );
if ( ! maskRgnMinusIconsWeAreMirroring )
{
maskRgnMinusIconsWeAreMirroring = NewRgn();
if ( maskRgnMinusIconsWeAreMirroring )
CopyRgn ( maskRgn, maskRgnMinusIconsWeAreMirroring );
}
if ( maskRgnMinusIconsWeAreMirroring )
DiffRgn ( maskRgnMinusIconsWeAreMirroring, animatedIcon->GetRgn(), maskRgnMinusIconsWeAreMirroring );
}
}
}
if ( srcBits == destBits && mode == srcCopy )
{
for ( LArrayIterator iter ( *gIconsOnScreen ); iter.Next( & animatedIcon ); )
{ short deltaH = srcRect->left - destRect->left;
short deltaV = srcRect->top - destRect->top;
if ( animatedIcon && ( & animatedIcon->GetPort()->portBits == srcBits ) )
{ Rect ourIconRect = animatedIcon->GetRect();
Rect intersectionRect;
if ( SectRect ( srcRect, & ourIconRect, & intersectionRect ) )
{
OffsetRect ( & ourIconRect, - deltaH, - deltaV );
animatedIcon->SetRect ( ourIconRect );
}
}
}
}
if ( maskRgnMinusIconsWeAreMirroring )
maskRgn = maskRgnMinusIconsWeAreMirroring;
CallCopyBits ( srcBits, destBits,srcRect, destRect, mode, maskRgn );
if ( maskRgnMinusIconsWeAreMirroring )
DisposeRgn ( maskRgnMinusIconsWeAreMirroring );
}
static Boolean DoesRectMatchOnOnScreenWindow ( const Rect* r )
{ Boolean result = false;
for ( WindowPeek windowP = (WindowPeek) FrontWindow(); windowP; windowP = (WindowPeek) windowP->nextWindow )
{
if ( EqualRect ( & ((WindowPtr) windowP)->portRect, r ) )
{
result = true;
break;
}
}
return result;
}
static pascal QDErr NewGWorldRoutine (GWorldPtr *offscreenGWorld, short PixelDepth,
const Rect *boundsRect, CTabHandle cTable,
GDHandle aGDevice, GWorldFlags flags)
{ OSErr err = CallNewGWorldRoutine ( offscreenGWorld, PixelDepth, boundsRect, cTable, aGDevice, flags );
if ( DoesRectMatchOnOnScreenWindow ( boundsRect ) )
{
dprintf ( "NewGWorldRoutine(), add %x to gWorld list", offscreenGWorld );
sFinderOffscreenGWorldList->InsertItemsAt ( 1, LArray::index_Last, & *offscreenGWorld, sizeof( *offscreenGWorld ) );
}
return err;
}
static pascal QDErr UpdateGWorldRoutine (GWorldPtr *offscreenGWorld, short PixelDepth,
const Rect *boundsRect, CTabHandle cTable,
GDHandle aGDevice, GWorldFlags flags)
{ OSErr err = CallUpdateGWorldRoutine ( offscreenGWorld, PixelDepth, boundsRect, cTable, aGDevice, flags );
return err;
}
static pascal void DisposeGWorldRoutine ( GWorldPtr offscreenGWorld )
{
if ( sFinderOffscreenGWorldList )
{
dprintf ( "DisposeGWorldRoutine(), removing %x to gWorld list", offscreenGWorld );
sFinderOffscreenGWorldList->Remove ( & offscreenGWorld, sizeof( offscreenGWorld ) );
}
CallDisposeGWorld ( offscreenGWorld );
}
static Boolean FinderIsActiveApp ( )
{ Boolean result = false;
StringPtr appName = LMGetCurApName();
if ( appName[0] == 6 && appName[1] == 'F' && appName[2] == 'i' &&
appName[3] == 'n' && appName[4] == 'd' && appName[5] == 'e' &&
appName[6] == 'r' )
{
result = true;
}
return result;
}
pascal Boolean MyGNEFilterRoutine ( EventRecord* event )
{ StUseSystemHeap saveZone;
Boolean result = true;
if ( event->what == nullEvent && gNextTickToCheckAnimations <= TickCount() && FinderIsActiveApp() )
{
gNextTickToCheckAnimations = InvalidateCurrentIcons ( );
}
#ifndef BUILDINGINIT
if ( IsOptionKeyDown() )
{
cout << "Icon suites & icon refs being replace:" << (*gIconsToAnimate).GetCount() << endl;
AnimatedIcon* animatedIcon = nil;
for ( LArrayIterator iter ( *gIconsToAnimate ); iter.Next( & animatedIcon ); )
{
cout << " " << (void*) animatedIcon << " Replaces:" << animatedIcon->GetIconSuiteThisReplaces() << endl;
}
cout << "Icons on Screen:" << (*gIconsToAnimate).GetCount() << endl;
AnimatedIconOnScreen* animatedIconOnScreen = nil;
for ( LArrayIterator iter ( *gIconsOnScreen ); iter.Next( & animatedIconOnScreen ); )
{
cout << " Grafport:" << animatedIconOnScreen->GetPort() <<
" Rect" << animatedIconOnScreen->GetRect().top << "," << animatedIconOnScreen->GetRect().left << "-" <<
animatedIconOnScreen->GetRect().bottom << ", " << animatedIconOnScreen->GetRect().right <<
" nextTick:" << animatedIconOnScreen->GetNextAnimationTick() - TickCount() <<
endl;
}
}
#endif
return result;
}
#define registersToSave a1-a5/d1-d7
pascal asm OSErr IconUtilitiesTrapPatch ()
{
bra.s @start
originalPatchAddress:
dc.l 0
myGlobals:
dc.l 0
@start:
cmp.w #0x0501, d0
beq.s @GetIconSuiteDispatch
cmp.w #0x0603, d0
beq.s @PlotIconSuiteDispatch
cmp.w #0x302, d0
beq @DisposeIconSuiteDispatch
move.l originalPatchAddress, -(sp)
rts
// pascal OSErr GetIconSuite ( Handle *theIconSuite, SInt16 theResID, IconSelectorValue selector );
//
@GetIconSuiteDispatch:
// _Debugger
link a6, #0
movem.l registersToSave, -(sp)
#ifdef BUILDINGINIT
move.l myGlobals, a4
#else
move.l myGlobals, a5
#endif
clr.w -(sp)
move.l 14(a6), -(sp)
move.w 12(a6), -(sp)
move.l 8(a6), -(sp)
jsr GetIconSuitePatch
move.w (sp)+, d0
movem.l (sp)+, registersToSave
unlk a6
move.l (sp)+, a0
add.l #10, sp
move.w d0, (sp)
jmp (a0)
// pascal OSErr PlotIconSuite (const Rect *theRect, IconAlignmentType align,
// IconTransformType transform, Handle theIconSuite)
//
// 4 return addr
// 8 theIconSuite
// 12 transform
// 14 align
// 16 theRect
// 20 result
//
@PlotIconSuiteDispatch:
// _Debugger
link a6, #0
movem.l registersToSave, -(sp)
#ifdef BUILDINGINIT
move.l myGlobals, a4
#else
move.l myGlobals, a5
#endif
clr.w -(sp) // space for result
move.l 16(a6), -(sp)
move.w 14(a6), -(sp)
move.w 12(a6), -(sp)
move.l 8(a6), -(sp)
jsr PlotIconSuitePatch
move.w (sp)+, d0
movem.l (sp)+, registersToSave
unlk a6
move.l (sp)+, a0
add.l #12, sp
move.w d0, (sp)
jmp (a0)
#if 0
@PlotIconSuiteMethodDispatch:
// _Debugger
link a6, #0
movem.l registersToSave, -(sp)
#ifdef BUILDINGINIT
move.l myGlobals, a4
#else
move.l myGlobals, a5
#endif
clr.w -(sp) // space for result
move.l 20(a6), -(sp)
move.w 18(a6), -(sp)
move.w 16(a6), -(sp)
move.w 12(a6), -(sp)
move.l 8(a6), -(sp)
jsr PlotIconSuiteMethodPatch
move.w (sp)+, d0
movem.l (sp)+, registersToSave
unlk a6
move.l (sp)+, a0
add.l #12, sp
move.w d0, (sp)
jmp (a0)
#endif
@DisposeIconSuiteDispatch:
// _Debugger
link a6, #0
movem.l registersToSave, -(sp)
#ifdef BUILDINGINIT
move.l myGlobals, a4
#else
move.l myGlobals, a5
#endif
clr.w -(sp) // space for result
move.l 10(a6), -(sp) // Boolean: disposeIcons
move.w 8(a6), -(sp) // Handle: iconSuiteH
jsr DisposeIconSuitePatch
move.w (sp)+, d0
movem.l (sp)+, registersToSave
unlk a6
move.l (sp)+, a0
add.l #6, sp
move.w d0, (sp)
jmp (a0)
}
pascal asm void InitGrafPatch ( GrafPtr )
{
bra.s @start
originalPatchAddress:
dc.l 0
myGlobals:
dc.l 0
@start:
movem.l d0, -(sp)
cmp.w #0x0646, 0x910
bne.s @callOriginalTrap
move.l 0x912, d0
cmp.l #0x696e6465, d0
bne.s @callOriginalTrap
cmp.b #'r', 0x916
bne.s @callOriginalTrap
link a6, #0
movem.l registersToSave, -(sp)
#ifdef BUILDINGINIT
move.l myGlobals, a4
#else
move.l myGlobals, a5
#endif
jsr InstallIconServicesPatches
jsr InstallCopyBitsPatch
movem.l (sp)+, registersToSave
unlk a6
@callOriginalTrap:
movem.l (sp)+, d0
move.l originalPatchAddress, -(sp)
rts
}
pascal asm void DisposeWindowPatch ( GrafPtr )
{
bra.s @start
originalPatchAddress:
dc.l 0
myGlobals:
dc.l 0
@start:
link a6, #0
movem.l registersToSave, -(sp)
#ifdef BUILDINGINIT
move.l myGlobals, a4
#else
move.l myGlobals, a5
#endif
move.l 8(a6), -(sp)
jsr DisposeWindowRoutine
movem.l (sp)+, registersToSave
unlk a6
@callOriginalTrap:
move.l originalPatchAddress, -(sp)
rts
}
pascal asm void HideWindowPatch ( GrafPtr )
{
bra.s @start
originalPatchAddress:
dc.l 0
myGlobals:
dc.l 0
@start:
link a6, #0
movem.l registersToSave, -(sp)
#ifdef BUILDINGINIT
move.l myGlobals, a4
#else
move.l myGlobals, a5
#endif
move.l 8(a6), -(sp)
jsr DisposeWindowRoutine
movem.l (sp)+, registersToSave
unlk a6
@callOriginalTrap:
move.l originalPatchAddress, -(sp)
rts
}
pascal asm OSErr IconServicesTrapPatch ()
{
bra.s @start
originalPatchAddress:
dc.l 0
myGlobals:
dc.l 0
@start:
cmp.w #0x03, d0
beq @GetIconRefFromFileInfoDispatch
cmp.w #0x0e, d0
beq @PlotIconRefDispatch
cmp.w #0x0d, d0
beq @DisposeIconRefDispatch
cmp.w #0x04, d0
beq @GetIconRefFromFolderInfoDispatch
cmp.w #0x02, d0
beq @GetIconRefFromFileDispatch
cmp.w #0x01, d0
beq @NewIconSuiteFromFileDispatch
move.l originalPatchAddress, -(sp)
rts
// pascal OSErr NewIconSuiteFromFile(const FSSpec *theFile, IconSelectorValue whichIcons, Handle *iconSuite, IconServicesUsageFlags iconServicesUsageFlags)
@NewIconSuiteFromFileDispatch:
link a6, #0
movem.l registersToSave, -(sp)
#ifdef BUILDINGINIT
move.l myGlobals, a4
#else
move.l myGlobals, a5
#endif
clr.w -(sp) // space for result
move.l 16(a6), -(sp) // theFile
move.l 16(a6), -(sp) // whichIcons
move.l 12(a6), -(sp) // *iconSuite
move.l 8(a6), -(sp) // iconServicesUsageFlags
jsr NewIconSuiteFromFilePatch
move.w (sp)+, d0
movem.l (sp)+, registersToSave
unlk a6
move.l (sp)+, a0
add.l #16, sp
move.w d0, (sp)
jmp (a0)
// pascal OSErr GetIconRefFromFile(const FSSpec *theFile, IconRef *iconRef, SInt16 *theLabel)
@GetIconRefFromFileDispatch:
link a6, #0
movem.l registersToSave, -(sp)
#ifdef BUILDINGINIT
move.l myGlobals, a4
#else
move.l myGlobals, a5
#endif
clr.w -(sp) // space for result
move.l 16(a6), -(sp) // *theFile
move.l 12(a6), -(sp) // *IconRef
move.l 8(a6), -(sp) // *theLabel
jsr GetIconRefFromFilePatch
move.w (sp)+, d0
movem.l (sp)+, registersToSave
unlk a6
move.l (sp)+, a0
add.l #12, sp
move.w d0, (sp)
jmp (a0)
// pascal OSErr GetIconRefFromFileInfoPatch ( const FSSpec *spec, IconRef *iconRef, OSType creatorCode, OSType fileType, Boolean hasCustomIcon )
@GetIconRefFromFileInfoDispatch:
link a6, #0
movem.l registersToSave, -(sp)
#ifdef BUILDINGINIT
move.l myGlobals, a4
#else
move.l myGlobals, a5
#endif
clr.w -(sp) // space for result
move.l 22(a6), -(sp) // spec
move.l 18(a6), -(sp) // *iconRef
move.l 14(a6), -(sp) // creator
move.l 10(a6), -(sp) // fileType
move.w 8(a6), -(sp) // boolean hasCustomIcon
jsr GetIconRefFromFileInfoPatch
move.w (sp)+, d0
movem.l (sp)+, registersToSave
unlk a6
move.l (sp)+, a0
add.l #18, sp
move.w d0, (sp)
jmp (a0)
// extern pascal OSErr GetIconRefFromFolderInfo(SInt16 vRefNum, SInt32 folderID, IconRef *iconRef, OSType fileType, Boolean hasCustomIcon)
@GetIconRefFromFolderInfoDispatch:
link a6, #0
movem.l registersToSave, -(sp)
#ifdef BUILDINGINIT
move.l myGlobals, a4
#else
move.l myGlobals, a5
#endif
clr.w -(sp) // space for result
move.w 22(a6), -(sp) // vRefNum
move.l 18(a6), -(sp) // folderID
move.l 14(a6), -(sp) // *iconRef
move.l 10(a6), -(sp) // fileType
move.w 8(a6), -(sp) // boolean hasCustomIcon
jsr GetIconRefFromFolderInfoPatch
move.w (sp)+, d0
movem.l (sp)+, registersToSave
unlk a6
move.l (sp)+, a0
add.l #16, sp
move.w d0, (sp)
jmp (a0)
// pascal OSErr PlotIconRef (const Rect *theRect, IconAlignmentType align,
// IconTransformType transform, IconRef iconRef )
//
// 4 return addr
// 8 theIconSuite
// 12 transform
// 14 align
// 16 theRect
// 20 result
//
@PlotIconRefDispatch:
link a6, #0
movem.l registersToSave, -(sp)
#ifdef BUILDINGINIT
move.l myGlobals, a4
#else
move.l myGlobals, a5
#endif
clr.w -(sp) // space for result
move.l 20(a6), -(sp) // rect
move.w 18(a6), -(sp) // align
move.w 16(a6), -(sp) // transform
move.l 12(a6), -(sp) // usageFlags
move.l 8(a6), -(sp) // iconRef
jsr PlotIconRefPatch
move.w (sp)+, d0
movem.l (sp)+, registersToSave
unlk a6
move.l (sp)+, a0
add.l #16, sp
move.w d0, (sp)
jmp (a0)
@DisposeIconRefDispatch:
// _Debugger
link a6, #0
movem.l registersToSave, -(sp)
#ifdef BUILDINGINIT
move.l myGlobals, a4
#else
move.l myGlobals, a5
#endif
clr.w -(sp) // space for result
move.l 8(a6), -(sp) // Handle: iconSuiteH
jsr DisposeIconRefPatch
move.w (sp)+, d0
movem.l (sp)+, registersToSave
unlk a6
move.l (sp)+, a0
add.l #4, sp
move.w d0, (sp)
jmp (a0)
}
// ============================================================================================
asm pascal void jGNEFilter ( )
{
bra.s @start
nextGNEFilterRoutine:
dc.l 0
myGlobals:
dc.l 0
// the EventRecord is pointed to by a1
// We return a true/false value in d0 as to whether to handle the event.
@start:
movem.l registersToSave, -(sp)
#ifdef BUILDINGINIT
move.l myGlobals, a4
#else
move.l myGlobals, a5
#endif
clr.w -(sp)
move.l a1, -(sp)
jsr MyGNEFilterRoutine
move.w (sp)+, d0
movem.l (sp)+, registersToSave
move.l nextGNEFilterRoutine, a0
cmp.l #0, a0
beq.s @1
move.l a0, -(sp)
@1:
rts
}
// ============================================================================================
asm pascal void CopyBitsPatch ( BitMap* srcBits, BitMap* destBits,
const Rect* srcRect, const Rect* destRect,
short mode, RgnHandle maskRgn )
{
bra.s @start
originalPatchAddress:
dc.l 0
myGlobals:
dc.l 0
// the EventRecord is pointed to by a1
// We return a true/false value in d0 as to whether to handle the event.
@start:
link a6, #0
movem.l registersToSave, -(sp)
#ifdef BUILDINGINIT
move.l myGlobals, a4
#else
move.l myGlobals, a5
#endif
move.l 26(a6), -(sp) // srcBits
move.l 22(a6), -(sp) // destBits
move.l 18(a6), -(sp) // srcRect
move.l 14(a6), -(sp) // destRect
move.w 12(a6), -(sp) // mode
move.l 8(a6), -(sp) // maskRgn
jsr CopyBitsRoutine
movem.l originalPatchAddress, a0
movem.l (sp)+, registersToSave
unlk a6
jmp (a0)
}
// ============================================================================================
asm pascal void QDExtensionsPatch ( )
{
bra.s @start
originalPatchAddress:
dc.l 0
myGlobals:
dc.l 0
//
@start:
cmp.w #0x0000, d0
beq.s @NewGWorldPatch
cmp.w #0x0004, d0
beq.s @DisposeGWorld
cmp.w #0x0003, d0
beq.s @UpdateGWorld
move.l originalPatchAddress, -(sp)
rts
@NewGWorldPatch:
link a6, #0
movem.l registersToSave, -(sp)
#ifdef BUILDINGINIT
move.l myGlobals, a4
#else
move.l myGlobals, a5
#endif
clr.w -(sp)
move.l 26(a6), -(sp) // srcBits
move.w 24(a6), -(sp) // destBits
move.l 20(a6), -(sp) // srcRect
move.l 16(a6), -(sp) // destRect
move.l 12(a6), -(sp) // mode
move.l 8(a6), -(sp) // maskRgn
jsr NewGWorldRoutine
move.w (sp)+, d0
movem.l (sp)+, registersToSave
unlk a6
move.l (sp)+, a0
add.l #22, sp
move.w d0, (sp)
jmp (a0)
// void DisposeGWorld ( GWorldPtr theGWorld )
@DisposeGWorld:
link a6, #0
movem.l registersToSave, -(sp)
#ifdef BUILDINGINIT
move.l myGlobals, a4
#else
move.l myGlobals, a5
#endif
move.l 8(a6), -(sp) // maskRgn
jsr DisposeGWorldRoutine
movem.l (sp)+, registersToSave
unlk a6
move.l (sp)+, a0
add.l #4, sp
jmp (a0)
@UpdateGWorld:
link a6, #0
movem.l registersToSave, -(sp)
#ifdef BUILDINGINIT
move.l myGlobals, a4
#else
move.l myGlobals, a5
#endif
clr.w -(sp)
move.l 26(a6), -(sp) // srcBits
move.w 24(a6), -(sp) // destBits
move.l 20(a6), -(sp) // srcRect
move.l 16(a6), -(sp) // destRect
move.l 12(a6), -(sp) // mode
move.l 8(a6), -(sp) // maskRgn
jsr UpdateGWorldRoutine
move.w (sp)+, d0
movem.l (sp)+, registersToSave
unlk a6
move.l (sp)+, a0
add.l #22, sp
move.w d0, (sp)
jmp (a0)
}